﻿using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TrackIT.Common;
using TrackIT.Common.Repositories;
using TrackIT.Common.Utils;
using TrackIT.Common.ViewModel;

namespace TrackIT.UnitTest.ViewModel
{
    [TestClass]
    public class TaskViewModelTest
    {
        [TestMethod]
        public void GetTaskList_ListContainsTasks_TasksUpdated()
        {
            MockWorkLogRepository workLogRepository = new MockWorkLogRepository();
            MockDateTimeProvider dateTimeProvider = new MockDateTimeProvider();
            IList<WorkEntry> workEntries = HelperUtil.WorkEntryStringsToEntities(HelperUtil.WorkListMultipleTasks);
            IList<Task> tasks = HelperUtil.WorkEntryEntitiesToTaskEntities(workEntries);
            workLogRepository.TaskList = tasks;
            dateTimeProvider.Current = DateTime.Now;

            TaskViewModel target = new TaskViewModel(workLogRepository, dateTimeProvider);
            target.GetTaskList();

            Assert.AreEqual(tasks.Count, target.Tasks.Count);
        }

        [TestMethod]
        public void ToggleActionAndShow_EmptyWorkLog_TaskStarted()
        {
            MockWorkLogRepository workLogRepository = new MockWorkLogRepository();
            MockDateTimeProvider dateTimeProvider = new MockDateTimeProvider();
            workLogRepository.NextActionType = WorkEntryType.Start;
            dateTimeProvider.Current = DateTime.Now;
            TaskViewModel target = new TaskViewModel(workLogRepository, dateTimeProvider);
            target.ToggleActionAndShow();

            DateTime expectedStartTime = Util.RemoveUnecessarySecondsParts(DateTime.Now);
            DateTime actualStartTime = target.CurrentWorkEntry.Start.Value;
          
            Assert.AreEqual(true, target.EnableCombo);
            Assert.AreEqual("Start", target.OperationLabel);
            Assert.AreEqual("", target.Description);
            Assert.AreEqual(null, target.SelectedTask);
            Assert.IsTrue(HelperUtil.IsTimeWithinMinutes(expectedStartTime, actualStartTime, 1));
            Assert.AreEqual(null, target.CurrentWorkEntry.Stop);
            Assert.IsFalse(string.IsNullOrWhiteSpace(target.TimeLabel));
        }

        [TestMethod]
        public void ToggleActionAndShow_TaskStarted_TaskStopped()
        {
            MockWorkLogRepository workLogRepository = new MockWorkLogRepository();
            MockDateTimeProvider dateTimeProvider = new MockDateTimeProvider();
            dateTimeProvider.Current = DateTime.Now;
            workLogRepository.NextActionType = WorkEntryType.Stop;
            TaskViewModel target = new TaskViewModel(workLogRepository, dateTimeProvider);
            
            WorkEntry expected = new WorkEntry("23456", Util.RemoveUnecessarySecondsParts(DateTime.Now), null);
            workLogRepository.CurrentWorkEntry = expected;

            target.ToggleActionAndShow();

            DateTime expectedStartTime = Util.RemoveUnecessarySecondsParts(DateTime.Now);
            DateTime expectedStopTime = Util.RemoveUnecessarySecondsParts(DateTime.Now);

            Assert.IsNotNull(target.CurrentWorkEntry.Start.Value);
            Assert.IsNotNull(target.CurrentWorkEntry.Stop.Value);
            DateTime actualStartTime = target.CurrentWorkEntry.Start.Value;
            DateTime actualStopTime = target.CurrentWorkEntry.Stop.Value;

            Assert.AreEqual(false, target.EnableCombo);
            Assert.AreEqual("Stop", target.OperationLabel);
            Assert.AreEqual(expected.Task, target.SelectedTask.Name);
            Assert.IsTrue(HelperUtil.IsTimeWithinMinutes(expectedStartTime, actualStartTime, 1));
            Assert.IsTrue(HelperUtil.IsTimeWithinMinutes(expectedStopTime, actualStopTime, 1));
            Assert.IsFalse(string.IsNullOrWhiteSpace(target.TimeLabel));       
        }

        [TestMethod]
        public void ToggleActionAndShow_TaskStopped_TaskStarted()
        {
            MockWorkLogRepository workLogRepository = new MockWorkLogRepository();
            MockDateTimeProvider dateTimeProvider = new MockDateTimeProvider();
            dateTimeProvider.Current = DateTime.Now;
            workLogRepository.NextActionType = WorkEntryType.Start;
            TaskViewModel target = new TaskViewModel(workLogRepository, dateTimeProvider);

            WorkEntry expected = new WorkEntry("Review", Util.RemoveUnecessarySecondsParts(DateTime.Now), Util.RemoveUnecessarySecondsParts(DateTime.Now.AddMinutes(5)));
            workLogRepository.CurrentWorkEntry = expected;

            target.ToggleActionAndShow();

            DateTime expectedStartTime = Util.RemoveUnecessarySecondsParts(DateTime.Now);

            Assert.IsNotNull(target.CurrentWorkEntry.Start.Value);
            Assert.IsNull(target.CurrentWorkEntry.Stop);
            DateTime actualStartTime = target.CurrentWorkEntry.Start.Value;

            Assert.AreEqual(true, target.EnableCombo);
            Assert.AreEqual("Start", target.OperationLabel);
            Assert.AreEqual("", target.Description);
            Assert.IsNull(target.SelectedTask);
            Assert.IsTrue(HelperUtil.IsTimeWithinMinutes(expectedStartTime, actualStartTime, 1));
            Assert.IsFalse(string.IsNullOrWhiteSpace(target.TimeLabel));
        }

        [TestMethod]
        public void CommitCurrentAction_NoCurrentWorkEntryAndStop_CommitNotAllowed()
        {
            MockWorkLogRepository workLogRepository = new MockWorkLogRepository();
            MockDateTimeProvider dateTimeProvider = new MockDateTimeProvider();
            dateTimeProvider.Current = DateTime.Now;
            workLogRepository.NextActionType = WorkEntryType.Stop;

            TaskViewModel target = new TaskViewModel(workLogRepository, dateTimeProvider);
            target.CurrentWorkEntry = null;
            Assert.IsFalse(target.CommitCurrentAction());
        }

        [TestMethod]
        public void CommitCurrentAction_NoSelectedTaskAndStart_CommitNotAllowed()
        {
            MockWorkLogRepository workLogRepository = new MockWorkLogRepository();
            MockDateTimeProvider dateTimeProvider = new MockDateTimeProvider();
            dateTimeProvider.Current = DateTime.Now;
            workLogRepository.NextActionType = WorkEntryType.Start;

            TaskViewModel target = new TaskViewModel(workLogRepository, dateTimeProvider);
            target.SelectedTask = null;
            Assert.IsFalse(target.CommitCurrentAction());
        }

        [TestMethod]
        public void CommitCurrentAction_TaskSelectedAndStart_CommitAllowed()
        {
            MockWorkLogRepository workLogRepository = new MockWorkLogRepository();
            MockDateTimeProvider dateTimeProvider = new MockDateTimeProvider();
            dateTimeProvider.Current = DateTime.Now;     
            workLogRepository.NextActionType = WorkEntryType.Start;

            TaskViewModel target = new TaskViewModel(workLogRepository, dateTimeProvider);            
            target.SelectedTask = new Task("12341", "");
            Assert.IsTrue(target.CommitCurrentAction());
            Assert.AreEqual(1, workLogRepository.StartCallCount);
            Assert.AreEqual(1, workLogRepository.SaveCallCount);
            Assert.AreEqual("12341", workLogRepository.Current.Task);
        }

        [TestMethod]
        public void CommitCurrentAction_StopTask_CommitAllowed()
        {
            MockWorkLogRepository workLogRepository = new MockWorkLogRepository();
            MockDateTimeProvider dateTimeProvider = new MockDateTimeProvider();
            dateTimeProvider.Current = Util.RemoveUnecessarySecondsParts(DateTime.Now);
            workLogRepository.CurrentWorkEntry = new WorkEntry("1215654", Util.RemoveUnecessarySecondsParts(dateTimeProvider.Now.AddMinutes(-60)), null);
            workLogRepository.NextActionType = WorkEntryType.Stop;

            TaskViewModel target = new TaskViewModel(workLogRepository, dateTimeProvider);

            Assert.IsTrue(target.CommitCurrentAction());
            Assert.AreEqual(1, workLogRepository.StopCallCount);
            Assert.AreEqual(1, workLogRepository.SaveCallCount);
            Assert.AreEqual("1215654", workLogRepository.Current.Task);
            Assert.AreEqual(dateTimeProvider.Current.AddMinutes(-60), workLogRepository.Current.Start);
            Assert.AreEqual(dateTimeProvider.Current, workLogRepository.Current.Stop);
        }
    }
}
